package com.example.chapter3.pojo;

import com.example.chapter3.pojo.definition.Animal;
import com.example.chapter3.pojo.definition.Person;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component
public class BussinessPerson implements Person, BeanNameAware,
        BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {

//因为＠A utow ired 提供这样的规则， 首先它会根据类型找到对应的 Bean,
    //如果对应类型的 Bean 不是唯一 的，那么它会根据其属性名称和 Bean 的名称进行匹配。如果匹配得
    //上，就会使用该 Bean：如果还无法匹配，就会抛出异常。
    //注意的是＠Autowired 是一个默认必须找到对应 Bean 的注解，如果不能确定其标注属
    //性一定会存在并且允许这个被标注的属性为 null ， 那么你可以配置＠Autowired 属性 required 为 false,
//    @Autowired(required = false)
//    private Animal dog = null;


    // IoC 容器还是无法区分采用哪个 Bean 的实例进行注入 ， 又或者说我们需要更加灵活的
    //机制来实现注入，那么＠Queli fier 可以满足你的这个愿望 。 它的配置项 value 需要一个字符串去定义，
    //它将与＠Autowired 组合在一起，通过类型和名称一起找到 Bean
//    @Autowired
//    @Qualifier("dog")
//    private Animal animal = null;

    private Animal animal = null;

//    public BussinessPerson(@Autowired @Qualifier("dog") Animal animal){
//        this.animal = animal;
//    }

    @Override
    public void service() {
        this.animal.use();
    }

    @Override
    @Autowired
    @Qualifier("dog")
    public void setAnimal(Animal animal) {
        System.out.println("延迟依赖注入");
        this.animal = animal;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("["+this.getClass().getSimpleName()+"]调用beanFactoryAware的setBeanFactor");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("["+this.getClass().getSimpleName()+"]调用BeanNameAware的setBeanName");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("["+this.getClass().getSimpleName()+"]InitalizingBean的afterPropertiesSet方法");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("["+this.getClass().getSimpleName()+"]ApplicationContextAware的setApplicationContext");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println ("[" + this.getClass().getSimpleName() + "]调用 ApplicationContextAware 的 setApplicationContext" );
    }

    @PreDestroy
    public void destroy1(){
        System.out.println("["+this.getClass().getSimpleName()+"]注解@PreDestroy定义的自定义销毁方法");
    }

    //这样，这个 Bean 就 实现了 生 命 周 期中单个 Bean 可以 实现的所 有 接口， 并且通过注解
    //@PostCons仕uct 定义 了 初始化方法 ，通过注解＠PreDestroy 定义了销毁方法 。
    @PostConstruct
    public void init(){
        System.out.println("["+this.getClass().getSimpleName()+"]注解PostConstruct定义的自定义初始化方法");
    }

}
